package com.wtwd.campus.utils;

import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.entity.*;
import com.wtwd.campus.service.CustomerService;
import com.wtwd.campus.service.RedisService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author ldaoliang
 * @Date create in 10:10 2021/7/6
 * @Description 推送数据到客户，如果失败则保存到数据库，等某一时刻统一推送
 */
@Component
public class PushUtils {

    private static final Logger logger = LoggerFactory.getLogger(PushUtils.class);

    @Autowired
    private CustomerService customerService;
    @Autowired
    private RedisService redisService;

    private static String account = "zzx_gps";
    private static final String HXY_FENCE_URL = "https://open-api.yn139jy.com/api/third/oneCard/message";
    private static final String HXY_MSG_URL = "https://open-api.yn139jy.com/api/third/oneCard/fence/";
    private static final String HXY_APPID = "MR8IGP4MVFW02JBPSXNH25X0KFPEH39E";
    private static final String HXY_APPSECRET = "P0FMHB2D1U7CQKVJZJPS051H0408E9T4";
    /**
     * h5客户(例如瑞翼...)对接湖南和教育平台的，将告警信息推送至湖南和教育平台(采用接口文档湖南和教育文档3.3.12)
     */

    private static final String hnhjyPushAlarmUrl = "https://hnhjyopenapi.hnsmartedu.com/typtoauth/WeChatPush";


    /**
     * 四川启迪推送地址
     */
    private static final String SCQD_WARN_URL = "http://att-ingress.cdqidi.cn/gps";

    /**
     * 现在只有一个客户（四川启迪）
     *
     * @param
     * @return
     */
    public String getToken(int customerId) {
        String redisToken = redisService.getValue(Constants.PUSH_TO_CUSTOMER_TOKEN_PREFIX + customerId);
        if (StringUtils.isNotBlank(redisToken)) {
            return redisToken;
        }
        // 从客户那获取
        String authenticationUrl = "http://att-ingress.cdqidi.cn/auth/sign";
        String pwd = "zzx_gps_123456";
        String token = MD5Utils.encode(pwd);
        long time = System.currentTimeMillis();
        String signature = MD5Utils.encode(token + time);
        Map<String, String> map = new HashMap<>();
        map.put("account", account);
        map.put("signature", signature);
        map.put("time", String.valueOf(time));
        JSONObject json = HttpclientUtil.postxWWWFormUrlEncode(authenticationUrl, map);
        if (json.getString("state").equals("ok")) {
            redisToken = json.getJSONObject("data").getString("access_token");
            // 从客户服务器获取token
            logger.info("从客户服务器获取token:" + redisToken);
            long expireTime = Long.valueOf(json.getJSONObject("data").getString("access_expires"));
            redisService.setKey(Constants.PUSH_TO_CUSTOMER_TOKEN_PREFIX + customerId, redisToken, 2500, TimeUnit.SECONDS);
            return redisToken;
        }
        return null;
    }

    /**
     * 推送定位数据  授权 认证
     *
     * @param mqLocationData
     * @param locationType
     * @param locationTime
     * @param deviceInfo
     */
    public void pushLocationData(MqLocationData mqLocationData, int locationType, Long locationTime,
                                 DeviceInfo deviceInfo) {
        SysCustomer sysCustomer = verifyCanPush(deviceInfo.getCustomerId());
        if (sysCustomer != null) {
            logger.info("推送参数：data={}", mqLocationData.toString());
            logger.info("推送地址不为空：" + sysCustomer.getPushUrl());
            JSONObject jsonObject = new JSONObject();
            PushLocation pushLocation = new PushLocation();
            pushLocation.setDirection(mqLocationData.getOrientation());
            pushLocation.setGate_time(DateUtils.format(new Date(), DateUtils.dateFormat4));
            pushLocation.setGps_info(mqLocationData.getGpsNum());
            pushLocation.setGps_speed(mqLocationData.getSpeed());
            pushLocation.setImei(deviceInfo.getImei());
            pushLocation.setPos_type(locationType);
            pushLocation.setLat(mqLocationData.getLatitude());
            pushLocation.setLng(mqLocationData.getLongitude());
            pushLocation.setGps_time(DateUtils.format(new Date(locationTime), DateUtils.dateFormat4));
            if (sysCustomer.getId() == 4) {
                //如果是四川启迪，则需要token
                String token = getToken(deviceInfo.getCustomerId());
                logger.info("获取推送到客户需要的token ：" + token);
                if (StringUtils.isBlank(token)) {
                    return;
                }
                jsonObject.put("token", token);
                jsonObject.put("account", account);
                List<PushLocation> pushLocationList = new ArrayList<>();
                pushLocationList.add(pushLocation);
                jsonObject.put("point_list", pushLocationList);
            } else {
                jsonObject = (JSONObject) JSONObject.toJSON(pushLocation);
            }
            String pushResult = push(sysCustomer.getPushUrl() + "/push", jsonObject);
            if (pushResult != null) {
                logger.info("推送失败");
                customerService.saveFailedPush(deviceInfo.getCustomerId(), deviceInfo.getImei(), pushResult);
            }
        }
    }

    /**
     * 推送围栏报警数据
     *
     * @param deviceInfo
     * @param mqLocationData
     * @param fenceId
     * @param fenceType
     */
    public void pushFenceWarn(DeviceInfo deviceInfo, MqLocationData mqLocationData, int fenceId, int fenceType) {
        SysCustomer sysCustomer = verifyCanPush(deviceInfo.getCustomerId());
        if (sysCustomer != null) {
            logger.info("推送地址不为空：" + sysCustomer.getPushUrl());
            JSONObject jsonObject = new JSONObject();
            PushWarn pushWarn = new PushWarn();
            pushWarn.setGeoid(fenceId);
            pushWarn.setSpeed(mqLocationData.getSpeed());
            pushWarn.setImei(deviceInfo.getImei());
            pushWarn.setLat(mqLocationData.getLatitude());
            pushWarn.setLng(mqLocationData.getLongitude());
            pushWarn.setType(fenceType == 0 ? 4 : 5);
            pushWarn.setPushtime(DateUtils.format(new Date(), DateUtils.dateFormat4));
            String pushResult;
            if (sysCustomer.getId() == 4) {
                //如果是四川启迪，则需要token
                String token = getToken(deviceInfo.getCustomerId());
                logger.info("获取推送到客户需要的token ：" + token);
                if (StringUtils.isBlank(token)) {
                    return;
                }
                jsonObject.put("token", token);
                jsonObject.put("account", account);
                List<PushWarn> pushWarnList = new ArrayList<>();
                pushWarnList.add(pushWarn);
                jsonObject.put("alarm_list", pushWarnList);
                pushResult = push(SCQD_WARN_URL + "/pushalarm", jsonObject);
            } else {
                jsonObject = (JSONObject) JSONObject.toJSON(pushWarn);
                pushResult = push(sysCustomer.getPushUrl() + "/pushWarn", jsonObject);
            }
            if (pushResult != null) {
                customerService.saveFailedPush(deviceInfo.getCustomerId(), deviceInfo.getImei(), pushResult);
            }
        }
    }

    /**
     * 推送SOS报警数据
     *
     * @param deviceInfo
     * @param mqLocationData
     */
    public void pushSOSWarn(DeviceInfo deviceInfo, MqLocationData mqLocationData) {
        SysCustomer sysCustomer = verifyCanPush(deviceInfo.getCustomerId());
        if (sysCustomer != null) {
            logger.info("推送地址不为空：" + sysCustomer.getPushUrl());
            JSONObject jsonObject = new JSONObject();
            PushWarn pushWarn = new PushWarn();
            pushWarn.setSpeed(mqLocationData.getSpeed());
            pushWarn.setImei(deviceInfo.getImei());
            pushWarn.setLat(mqLocationData.getLatitude());
            pushWarn.setLng(mqLocationData.getLongitude());
            pushWarn.setType(1);
            pushWarn.setPushtime(DateUtils.format(new Date(), DateUtils.dateFormat4));
            String pushResult;
            if (sysCustomer.getId() == 4) {
                //如果是四川启迪，则需要token
                String token = getToken(deviceInfo.getCustomerId());
                logger.info("获取推送到客户需要的token ：" + token);
                if (StringUtils.isBlank(token)) {
                    return;
                }
                jsonObject.put("token", token);
                jsonObject.put("account", account);
                List<PushWarn> pushWarnList = new ArrayList<>();
                pushWarnList.add(pushWarn);
                jsonObject.put("alarm_list", pushWarnList);
                pushResult = push(SCQD_WARN_URL + "/pushalarm", jsonObject);
            } else {
                jsonObject = (JSONObject) JSONObject.toJSON(pushWarn);
                pushResult = push(sysCustomer.getPushUrl() + "/pushWarn", jsonObject);
            }
            if (pushResult != null) {
                customerService.saveFailedPush(deviceInfo.getCustomerId(), deviceInfo.getImei(), pushResult);
            }
        }
    }

    /**
     * 推送低电报警
     *
     * @param deviceInfo
     */
    public void pushLowBatteryWarn(DeviceInfo deviceInfo) {
        SysCustomer sysCustomer = verifyCanPush(deviceInfo.getCustomerId());
        if (sysCustomer != null) {
            logger.info("推送地址不为空：" + sysCustomer.getPushUrl());
            JSONObject jsonObject = new JSONObject();
            PushWarn pushWarn = new PushWarn();
            pushWarn.setSpeed(0);
            pushWarn.setImei(deviceInfo.getImei());
            pushWarn.setLat(0);
            pushWarn.setLng(0);
            pushWarn.setType(90);
            pushWarn.setPushtime(DateUtils.format(new Date(), DateUtils.dateFormat4));
            String pushResult;
            if (sysCustomer.getId() == 4) {
                //如果是四川启迪，则需要token
                String token = getToken(deviceInfo.getCustomerId());
                logger.info("获取推送到客户需要的token ：" + token);
                if (StringUtils.isBlank(token)) {
                    return;
                }
                jsonObject.put("token", token);
                jsonObject.put("account", account);
                List<PushWarn> pushWarnList = new ArrayList<>();
                pushWarnList.add(pushWarn);
                jsonObject.put("alarm_list", pushWarnList);
                pushResult = push(SCQD_WARN_URL + "/pushalarm", jsonObject);
            } else {
                jsonObject = (JSONObject) JSONObject.toJSON(pushWarn);
                pushResult = push(sysCustomer.getPushUrl() + "/pushWarn", jsonObject);
            }
            if (pushResult != null) {
                customerService.saveFailedPush(deviceInfo.getCustomerId(), deviceInfo.getImei(), pushResult);
            }
        }
    }

    /**
     * 推送开机告警记录
     *
     * @param deviceInfo
     */
    public void pushPowerOnWarn(DeviceInfo deviceInfo) {
        SysCustomer sysCustomer = verifyCanPush(deviceInfo.getCustomerId());
        if (sysCustomer != null) {
            logger.info("推送地址不为空：" + sysCustomer.getPushUrl());
            JSONObject jsonObject = new JSONObject();
            PushWarn pushWarn = new PushWarn();
            pushWarn.setSpeed(0);
            pushWarn.setImei(deviceInfo.getImei());
            pushWarn.setLat(0);
            pushWarn.setLng(0);
            pushWarn.setType(12);
            pushWarn.setPushtime(DateUtils.format(new Date(), DateUtils.dateFormat4));
            String pushResult;
            if (sysCustomer.getId() == 4) {
                //如果是四川启迪，则需要token
                String token = getToken(deviceInfo.getCustomerId());
                logger.info("获取推送到客户需要的token ：" + token);
                if (StringUtils.isBlank(token)) {
                    return;
                }
                jsonObject.put("token", token);
                jsonObject.put("account", account);
                List<PushWarn> pushWarnList = new ArrayList<>();
                pushWarnList.add(pushWarn);
                jsonObject.put("alarm_list", JSONObject.toJSONString(pushWarnList));
                pushResult = push(SCQD_WARN_URL + "/pushalarm", jsonObject);
            } else {
                jsonObject = (JSONObject) JSONObject.toJSON(pushWarn);
                pushResult = push(sysCustomer.getPushUrl() + "/pushWarn", jsonObject);
            }
            if (pushResult != null) {
                customerService.saveFailedPush(deviceInfo.getCustomerId(), deviceInfo.getImei(), pushResult);
            }
        }
    }


    /**
     * 推送关机告警记录
     *
     * @param deviceInfo
     */
    public void pushShutDownWarn(DeviceInfo deviceInfo) {
        SysCustomer sysCustomer = verifyCanPush(deviceInfo.getCustomerId());
        if (sysCustomer != null) {
            logger.info("推送地址不为空：" + sysCustomer.getPushUrl());
            JSONObject jsonObject = new JSONObject();
            PushWarn pushWarn = new PushWarn();
            pushWarn.setSpeed(0);
            pushWarn.setImei(deviceInfo.getImei());
            pushWarn.setLat(0);
            pushWarn.setLng(0);
            pushWarn.setType(17);
            pushWarn.setPushtime(DateUtils.format(new Date(), DateUtils.dateFormat4));
            String pushResult;
            if (sysCustomer.getId() == 4) {
                //如果是四川启迪，则需要token
                String token = getToken(deviceInfo.getCustomerId());
                logger.info("获取推送到客户需要的token ：" + token);
                if (StringUtils.isBlank(token)) {
                    return;
                }
                jsonObject.put("token", token);
                jsonObject.put("account", account);
                List<PushWarn> pushWarnList = new ArrayList<>();
                pushWarnList.add(pushWarn);
                jsonObject.put("alarm_list", JSONObject.toJSONString(pushWarnList));
                pushResult = push(SCQD_WARN_URL + "/pushalarm", jsonObject);
            } else {
                jsonObject = (JSONObject) JSONObject.toJSON(pushWarn);
                pushResult = push(sysCustomer.getPushUrl() + "/pushWarn", jsonObject);
            }
            if (pushResult != null) {
                customerService.saveFailedPush(deviceInfo.getCustomerId(), deviceInfo.getImei(), pushResult);
            }
        }
    }

    /**
     * @param customerId 设备的客户id
     * @return
     */
    private SysCustomer verifyCanPush(Integer customerId) {
        SysCustomer sysCustomer = customerService.getSysCustomerById(customerId);
        if (sysCustomer == null) {
            return null;
        }
        if (StringUtils.isBlank(sysCustomer.getPushUrl()) || sysCustomer.getDisableSwitch() == 1) {
            return null;
        }
        return sysCustomer;
    }

    /**
     * 推送数据
     *
     * @param pushUrl
     * @param jsonObject
     * @return
     */
    private String push(String pushUrl, JSONObject jsonObject) {
        String jsonString = jsonObject.toJSONString();
        logger.info("推送地址：" + pushUrl);
        logger.info("推送内容：" + jsonObject);
        try {
            String result = HttpclientUtil.httpPost(pushUrl, jsonObject);
            JSONObject json = JSONObject.parseObject(result);
            logger.info("推送结果：" + json);
            if (json.getString("state").equals("ok")) {
                return null;
            }
        } catch (Exception e) {
            logger.error("推送异常 " + e);
            return jsonString;
        }
        return jsonString;
    }

    /**
     * 推送数据
     *
     * @param pushUrl
     * @param jsonObject
     * @return
     */
    private String pushAlarm(String pushUrl, JSONObject jsonObject) {
        logger.info("推送地址：" + pushUrl);
        logger.info("推送内容：" + jsonObject);
        try {
            String result = HttpclientUtil.get(pushUrl, jsonObject);
            JSONObject json = JSONObject.parseObject(result);
            logger.info("推送结果：" + json);
            if (json.getString("state").equals("ok")) {
                return null;
            }
        } catch (Exception e) {
            logger.error("推送异常 " + e);
            return jsonObject.toJSONString();
        }
        return jsonObject.toJSONString();
    }


    /**
     * 进出围栏推送
     *
     * @param imei
     * @param type
     * @param uploadTime
     * @param longitude
     * @param latitude
     * @param fenceId
     */
    public void pushHxyFenceWarn(String imei, String type, String uploadTime, Double longitude, Double latitude, String fenceId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("imei", imei);
        jsonObject.put("dataType", Integer.parseInt(type));
        jsonObject.put("uploadTime", uploadTime);
        jsonObject.put("fenceId", fenceId);
        jsonObject.put("longitude", longitude);
        jsonObject.put("latitude", latitude);
        String s = HttpclientUtil.postWithJSON(HXY_FENCE_URL, jsonObject, createHxyRequestHeader());
        logger.info("推送和校园进出围栏---->" + jsonObject + "---结果：" + s);
    }

    /**
     * 推送开机
     *
     * @param imei
     * @param uploadTime
     */
    public void pushHxyPowerOn(String imei, String uploadTime) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("imei", imei);
        jsonObject.put("dataType", 1);
        jsonObject.put("uploadTime", uploadTime);
        String s = HttpclientUtil.postWithJSON(HXY_FENCE_URL, jsonObject, createHxyRequestHeader());
        logger.info("推送和校园开机---->" + jsonObject + "---结果：" + s);
    }

    /**
     * 低电推送
     *
     * @param imei
     * @param uploadTime
     * @param battery
     */
    public void pushHxyLowBattery(String imei, String uploadTime, Integer battery) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("imei", imei);
        jsonObject.put("dataType", 3);
        jsonObject.put("uploadTime", uploadTime);
        jsonObject.put("battery", battery);
        String s = HttpclientUtil.postWithJSON(HXY_FENCE_URL, jsonObject, createHxyRequestHeader());
        logger.info("推送和校园低电---->" + jsonObject + "---结果：" + s);
    }

    /**
     * 关机推送
     *
     * @param imei
     * @param uploadTime
     */
    public void pushHxyShutDown(String imei, String uploadTime) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("imei", imei);
        jsonObject.put("dataType", 2);
        jsonObject.put("uploadTime", uploadTime);
        String s = HttpclientUtil.postWithJSON(HXY_FENCE_URL, jsonObject, createHxyRequestHeader());
        logger.info("推送和校园关机---->" + jsonObject + "---结果：" + s);
    }

    /**
     * SOS报警推送
     *
     * @param imei
     * @param longitude
     * @param latitude
     * @param uploadTime
     */
    public void pushHxySos(String imei, Double longitude, Double latitude, String uploadTime) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("imei", imei);
        jsonObject.put("dataType", 4);
        jsonObject.put("uploadTime", uploadTime);
        jsonObject.put("longitude", longitude);
        jsonObject.put("latitude", latitude);
        String s = HttpclientUtil.postWithJSON(HXY_FENCE_URL, jsonObject, createHxyRequestHeader());
        logger.info("推送和校园SOS---->" + jsonObject + "---结果：" + s);
    }


    public Map<String, String> createHxyRequestHeader() {
        HashMap<String, String> header = new HashMap<>();
        long timestamp = System.currentTimeMillis();
        header.put("appId", HXY_APPID);
        header.put("timestamp", String.valueOf(timestamp));
        header.put("sign", SignUtil.md5(HXY_APPID + HXY_APPSECRET + timestamp).toLowerCase());
        return header;
    }


    public void hnh5PushAlarmInfo(String imei, String alertType, String uploadTime, String address, Integer fenceType, String fenceName) {
        JSONObject data = new JSONObject();
        data.put("alert_type", alertType);
        data.put("uploadTime", uploadTime);
        data.put("address", address);
        data.put("fence_type", fenceType);
        data.put("Fence_name", fenceName);
        String s = null;
        try {
            s = URLEncoder.encode(data.toJSONString(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String reqUrl = hnhjyPushAlarmUrl.concat("?imei=").concat(imei).concat("&alertdata=").concat(s);
        String rest = HttpclientUtil.get(reqUrl);
        logger.info("推送湖南和教育 参数" + imei + data.toJSONString() + "推送结果：" + rest);
    }


}
